import {
  ROOM_STATUS,
  PLAYER_STATUS,
  roomStatusToString,
  playerStatusToString,
} from '../../STATUS';
import TWEEN, {
  L_ANI_TIME,
  B_ANI_TIME,
  M_ANI_TIME,
  S_ANI_TIME,
  Tween,
} from "../../core/Tween";
import {
  on
} from '../../core/componentGenerator';

export function init_loader(loader) {
  loader.add("bg", "game/Game_BJ-my.jpg");
  loader.add("avatar_box", "game/Avatarbox_2.png");
  loader.add("ready", "game/ready_03.png"); // 已准备
  loader.add("done", "game/State_01.png"); // 完成摆牌
  loader.add("playing", "game/State_02.png"); // 摆牌中
  loader.add("to_online", "game/State_03.png"); // 连接中
  loader.add("outline", "game/State_04.png"); // 断线

  loader.add("chat_btm", "game/chat_01.png"); // 聊天按钮
  loader.add("common_msg_box", "game/chat_04.png"); // 常用语框
  loader.add("msg_bg", "game/Chat_UI_01.png"); // 常用语框
  loader.add("msg_send_btm", "game/msg_send_btm.png"); // 常用语框
  loader.add("msg_from_bottom", "game/Chatpop01.png");
  loader.add("msg_from_top", "game/Chatpop03.png");
  loader.add("msg_from_left", "game/Chatpop04.png");
  loader.add("msg_from_right", "game/Chatpop02.png");
}
export default async function render_player(args, is_show_status = false) {
  const {
    app,
    stage,
    resources,
    width,
    height,
    un_watch, // 不监听变动
    players,
    unwatchers,
  } = args;

  const ani_tween = new TWEEN();
  app._ticker.add(() => {
    // 动画控制器
    ani_tween.update();
  });
  /* 当前玩家*/
  // 用户信息
  const $cur_player = new PIXI.Container();
  stage.addChild($cur_player);
  let $avatar_box = new PIXI.Sprite(resources.avatar_box.texture);
  $avatar_box.maxWidthHeight(width / 5, height / 5);
  let avatar_box_bounds;
  let {
    width: avatar_box_width,
    height: avatar_box_height
  } = $avatar_box;
  $avatar_box.destroy();
  $avatar_box = null;

  /* 其它玩家*/

  const $other_players = new PIXI.Container();
  stage.addChild($other_players);

  const player_cache = [];
  // 其它用户
  const render_other_player = (player, x, y, parent) => {
    // 销毁子元素
    const is_use_cache = !!parent.children.length;
    if (is_use_cache) {
      // 老对象，销毁子元素
      parent.children.slice().forEach(item => {
        if (item !== parent._cache_$txt && item !== $avatar_box) {
          item.destroy()
        }
      });
    } else {
      // 新元素，进行强制定位
      parent.x = x;
      parent.y = y;
      parent.getSourcePos = () => {
        return {
          x,
          y
        }
      }
      parent.moveTo = (_x = 0, _y = 0) => {
        parent.x = /*-x +*/ _x
        parent.y = /*-y +*/ _y
      };
      parent.getPos = () => {
        return {
          x: parent.x,
          y: parent.y
        }
      };
      parent.setStatusHandler = (statusHandler) => {
        parent.handleStatus = statusHandler;
        if (parent.handleStatus instanceof Function) {
          parent.handleStatus($status);
        }
      }
    }
    // 渲染用户信息
    const $avatar_box = new PIXI.Sprite(resources.avatar_box.texture);
    $avatar_box.maxWidthHeight(width / 5, height / 5);
    const avatar_box_bounds = $avatar_box.getBounds();
    parent.addChild($avatar_box);
    const info = player.info;
    const {
      headimgurl,
      username
    } = info;
    const player_id = this.player.id;
    const $userhead = new PIXI.Sprite.fromImage(`${server_href}/proxy?src=${encodeURIComponent(headimgurl)}`);
    $userhead.id = window.$userhead_id = (window.$userhead_id | 0) + 1;
    const $userhead_texture = $userhead.texture
    $userhead_texture.on("update", function update(tex, is_keep) {
      try {
        $userhead.width = avatar_box_bounds.width * 0.76
        $userhead.height = $userhead.width;
        $userhead.x = avatar_box_bounds.width / 2 - $userhead.width / 2;
        $userhead.y = avatar_box_bounds.height / 2 - $userhead.height / 2 - avatar_box_bounds.height * 0.025;
        if (!is_keep) {
          $userhead_texture.off("update", update);
        }
      } catch (e) {
        console.error("渲染异常，请刷新浏览器重试")
      }
    });
    $userhead_texture.emit("update", null, !$userhead_texture.valid);

    const fontSize = avatar_box_bounds.height / 7;

    const $username = new PIXI.Text(username, {
      fontSize: fontSize,
      fill: 0xFFFFFF
    });
    $username.alpha = 0.9;
    // $username.x = $userhead.x + $userhead.width + 5;
    $username.x = avatar_box_bounds.width / 2 - $username.width / 2;
    $username.y = fontSize * 0.1;

    parent.addChildBefore($userhead, $avatar_box);
    parent.addChildAfter($username, $avatar_box);
    // 状态渲染
    const $status = new PIXI.Sprite(resources.to_online.texture);
    $status.maxHeight(avatar_box_bounds.height / 4);
    $status.x = avatar_box_bounds.width / 2 - $status.width / 2;
    $status.y = avatar_box_bounds.height / 2 - $status.height / 2;
    parent.addChild($status);
    const status = player.status;
    if (player.is_online) {
      $status.visible = true
      if (status === PLAYER_STATUS.READY) {
        $status.texture = resources.ready.texture
      } else if (status === PLAYER_STATUS.BEFORE_SUBMIT) {
        $status.texture = resources.playing.texture
      } else if (status === PLAYER_STATUS.AFTER_SUBMIT) {
        $status.texture = resources.done.texture
      } else {
        $status.visible = false
      }
    } else {
      $status.texture = resources.outline.texture
    }
    if (parent.handleStatus instanceof Function) {
      parent.handleStatus($status);
    }
    let status_visible = $status.visible;
    parent.hideStatus = (time) => {
      if (time) {
        ani_tween.Tween
      } else {
        $status.visible = false
      }
    };
    parent.showStatus = (time) => {
      if (time) {
        ani_tween.Tween
      } else {
        $status.visible = status_visible
      }
    };
    // console.log(avatar_box_bounds)
    parent.showText = ($txt) => {
      if (parent._cache_$txt) {
        parent._cache_$txt.destroy();
        // parent._cache_$txt = null;
      }
      $txt.x = avatar_box_bounds.width / 2 - $txt.width / 2;
      $txt.y = avatar_box_bounds.height * 0.85 - $txt.height / 2;
      parent._cache_$txt = $txt;
      parent.addChildAfter($txt, $avatar_box);
    };
    if (is_use_cache && parent._cache_$txt) {
      parent.addChildAfter(parent._cache_$txt, $avatar_box);
    }
    return {
      $avatar_box
    }
  }
  const render_other_players = (players, cb) => {
    const player = this.player;
    if (!player.id) {
      console.error("当前用户信息未获取")
      return
    }
    if (!players.length) {
      console.error("房间用户信息未获取")
      return
    }

    const other_players = players.filter(o_player => o_player.id !== player.id);

    const [
      player_1,
      player_2,
      player_3,
    ] = other_players;

    if (player) {
      $cur_player.player_id = player.id;
      $avatar_box = render_other_player(player,
        width / 2 - avatar_box_width / 2,
        height - avatar_box_height * 1.2,
        $cur_player).$avatar_box;
      avatar_box_bounds = $avatar_box.getBounds();
      $cur_player.hideStatus();
    }

    const avator_pos = {
      get 0() {
        return [
          width / 2 - avatar_box_width / 2,
          avatar_box_height * .2,
        ]
      },
      get 1() {
        return [
          avatar_box_width * .2,
          height / 2 - avatar_box_height / 2,
        ]
      },
      get 2() {
        return [
          width - avatar_box_width * 1.2,
          height / 2 - avatar_box_height / 2,
        ]
      },
    };

    [
      player_1,
      player_2,
      player_3,
    ].forEach((player, i) => {
      let $other_player = player_cache[i]
      if (player) {
        $other_player || (() => {
          $other_player = player_cache[i] = new PIXI.Container();
          $other_player.player_id = player.id;
          $other_players.addChild($other_player);
        })();
        render_other_player(player,
          ...avator_pos[i],
          $other_player)
      } else if ($other_player) {
        player_cache[i] = null
        $other_player.destroy();
      }
    });

    if (avatar_box_bounds) {
      cb({
        avatar_box_bounds,
        $cur_player,
        $other_players,
      })
    }
  }

  // 渲染聊天工具
  const render_msg_tool = () => {

    const $chat_btm = new PIXI.Sprite(resources.chat_btm.texture);
    $chat_btm.maxWidth(avatar_box_width * 0.8);
    $chat_btm.x = width - $chat_btm.width * 1.1;
    $chat_btm.y = avatar_box_height * 0.2;
    $chat_btm.hover();
    stage.addChild($chat_btm);

    const $msg_dialog = new PIXI.Container();
    const $msg_dialog_bg = new PIXI.Sprite(resources.common_msg_box.texture);
    $msg_dialog_bg.maxWidth(Math.min($chat_btm.width * 12, width * 0.8));
    $msg_dialog.addChild($msg_dialog_bg);

    $msg_dialog.x = $chat_btm.x + $chat_btm.width - $msg_dialog_bg.width;
    $msg_dialog.y = $chat_btm.y + $chat_btm.height;
    stage.addChild($msg_dialog);
    $msg_dialog.close = () => {
      $msg_dialog.visible = false;
      $msg_dialog.emit("close")
    }
    $msg_dialog.open = () => {
      $msg_dialog.visible = true;
      $msg_dialog.emit("open")
    }
    $msg_dialog.toggle = () => {
      this.msg_box.is_open = !this.msg_box.is_open;
    }
    const $msg_send_btm = new PIXI.Sprite(resources.msg_send_btm.texture);
    $msg_send_btm.maxWidth($msg_dialog_bg.width * 0.12);
    $msg_send_btm.x = $msg_dialog_bg.width * 0.84;
    $msg_send_btm.y = $msg_dialog_bg.height * 0.86;
    $msg_send_btm.hover();
    $msg_dialog.addChild($msg_send_btm);

    $chat_btm.bindTap($msg_dialog.toggle);

    const msg_font_size = $msg_dialog.width / 20;

    [
      "快点吧，我等得裤子都没了！",
      "小心了！这把牌我要全垒打了！",
      "哇，这牌怎么摆？！",
      "来接受我的枪口把！",
      "五毒，炸弹，三尖刀。",
      "这游戏跟我一点关系也没有。",
    ].forEach((msg, i) => {
      const $msg = new PIXI.Text(msg, {
        fontSize: msg_font_size,
        fill: 0xFFFFFF
      });
      $msg.x = msg_font_size * 2;
      $msg.y = $msg_dialog.height * (i * 0.125 + 0.09); //+ 0.19
      $msg_dialog.addChild($msg);

      $msg.hover(() => {
        $msg.tint = 0x33FF33;
      });
      $msg.bindTap(() => {
        socket && socket.emit("send-msg", {
          msg
        });
        $msg_dialog.close();
      });
    });
    // custom input
    let input_ele = document.getElementById("custom-msg-input");
    if (!input_ele) {
      const ele_con = document.createElement("div");
      const max_length = 14;
      ele_con.innerHTML = `<input id="custom-msg-input" class="pixi-canvas-input" maxlength="${max_length}"/>`
      input_ele = ele_con.firstElementChild;
      input_ele.addEventListener("input", function () {
        if (this.value.length > max_length) {
          this.value = this.value.substr(0, max_length);
        }
      });
      input_ele.style.display = "none";
      document.body.appendChild(input_ele);
    }
    $msg_send_btm.bindTap(() => {
      const msg = input_ele.value.trim();
      if (msg) {
        socket && socket.emit("send-msg", {
          msg
        });
        input_ele.value = "";
        $msg_dialog.close();
      }
    });
    $msg_dialog.on("open", () => {
      input_ele.style.display = "block";
      // 位置要对上，IOS有跟随输入框的特性。
      input_ele.style.left = ($msg_dialog.x + $msg_dialog.width * 0.1) + "px";
      input_ele.style.top = ($msg_dialog.y + $msg_dialog.height * 0.85) + "px";
      input_ele.style.height = $msg_dialog.height * 0.1 + "px";
      input_ele.style.width = $msg_dialog.width * 0.7 + "px";
      input_ele.style.fontSize = msg_font_size + "px";
      input_ele.style.color = "#FFF";
    });
    $msg_dialog.on("close", () => {
      input_ele.blur();
      input_ele.onblur = null;
      console.log("CLOSE!!")
      input_ele.style.display = "none";
    });
    unwatchers[unwatchers.length] = this.$watch("msg_box.is_open", is_open => {
      if (is_open) {
        $msg_dialog.open();
      } else {
        $msg_dialog.close();
      }
    }, {
      immediate: true
    });

    unwatchers[unwatchers.length] = on(socket, "player-send-msg", ({
      player_id,
      player_name,
      msg
    }) => {
      console.log(player_id, player_name, msg);
      let msg_box_pos;
      if (player_id === this.player.id) {
        msg_box_pos = "bottom"
      } else {
        const other_players = this.room.players.filter(o_player => o_player.id !== this.player.id);
        const [
          player_1,
          player_2,
          player_3,
        ] = other_players;
        if (player_id === player_1.id) {
          msg_box_pos = "top"
        } else if (player_id === player_2.id) {
          msg_box_pos = "left"
        } else if (player_id === player_3.id) {
          msg_box_pos = "right"
        }
      }
      if (!msg_box_pos) {
        return
      }
      const $msg_box = new PIXI.Container();
      const $msg_box_bg = new PIXI.Sprite(resources["msg_from_" + msg_box_pos].texture);
      $msg_box_bg.maxWidth(Math.min(avatar_box_width * 6, width / 2));
      $msg_box.addChild($msg_box_bg);
      const msg_text_fontSize = $msg_box_bg.width / 15;
      const $msg_text = new PIXI.Text(msg, {
        fontSize: msg_text_fontSize,
        fill: 0xFFFFFF,
      });
      $msg_text.alpha = 0.8;
      $msg_text.y = $msg_box_bg.height * 0.34 - msg_text_fontSize / 2;
      if (msg_box_pos === "top") {
        $msg_text.y += $msg_box_bg.height * 0.3;
      }
      $msg_text.x = $msg_box_bg.width / 2 - $msg_text.width / 2;
      $msg_box.addChild($msg_text);

      stage.addChild($msg_box);
      if (msg_box_pos === "bottom") {
        $msg_box.x = width / 2 - $msg_box.width * 0.45;
        $msg_box.y = $cur_player.y - $msg_box.height;
      } else if (msg_box_pos === "top") {
        const $player_parent = player_cache[0];
        $msg_box.x = width / 2 - $msg_box.width * 0.60;
        $msg_box.y = $player_parent.y + $player_parent.height;
      } else if (msg_box_pos === "left") {
        const $player_parent = player_cache[1];
        $msg_box.x = $player_parent.x + $player_parent.width;
        $msg_box.y = $player_parent.y + $player_parent.height / 2 - $msg_box.height;
      } else if (msg_box_pos === "right") {
        const $player_parent = player_cache[2];
        $msg_box.x = $player_parent.x - $msg_box.width;
        $msg_box.y = $player_parent.y + $player_parent.height / 2 - $msg_box.height;
      } else {
        $msg_box.x = width / 2 - $msg_box.width / 2;
        $msg_box.y = height / 2 - $msg_box.height / 2;
      }
      setTimeout(() => {
        $msg_box.destroy();
      }, 2000);
    });
  };

  return new Promise((resolve) => {
    const runner = () => {
      render_other_players(players || this.room.players, resolve)
    }
    if (!un_watch) {
      for (let watch_key of ["room.players", "player.id"]) {
        unwatchers[unwatchers.length] = this.$watch(watch_key, runner);
      }
    }
    runner(); // immediate
    setTimeout(render_msg_tool);
  });
}
